package mt.dummy;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import mt.Order;
import mt.comm.ClientComm;
import mt.comm.ClientSideMessage;
import mt.comm.ServerSideMessage;

/**
 * ClientCommDummy is used by the GUI of the client to communicate with the
 * server.
 * 
 * @author Pedro,Rita,Miguel
 *
 */
public class ClientCommDummy implements ClientComm {

        private Socket socket;

        private ObjectOutputStream out;
        private ObjectInputStream in;
        private BlockingQueue<ClientMessage> q = new ArrayBlockingQueue<ClientMessage>(
                        100);
        private String nickname;
        private boolean isConnected = false;

        @Override
        public void connect(String serverAddress, String nickname) {
                this.nickname = nickname;
                try {
                        socket = new Socket(serverAddress, ServerCommDummy.PORTO);
                        in = new ObjectInputStream(socket.getInputStream());
                        out = new ObjectOutputStream(socket.getOutputStream());
                        isConnected = true;
                        ServerMessage msg = new ServerMessage(
                                        ServerSideMessage.Type.CONNECTED, nickname, null);
                        out.writeObject(msg);
                        new Receive(in, out).start();
                } catch (UnknownHostException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                }

        }

        /**
         * This Threads receives and processed the ClientMessage.
         */
        class Receive extends Thread {

                private ObjectInputStream in;
                //private ObjectOutputStream out;

                public Receive(ObjectInputStream in, ObjectOutputStream out) {
                        this.in = in;
                        //this.out = out;
                }

                @Override
                public void run() {
                        try {
                                while (isConnected()) {
                                        ClientMessage msg = (ClientMessage) in.readObject();
                                        q.add(msg);
                                }
                        } catch (IOException e) {
                        } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                        }
                }
        }

        @Override
        public boolean isConnected() {
                return isConnected;
        }

        @Override
        public void disconnect() {
                try {
                        isConnected = false;
                        out.writeObject(new ServerMessage(ServerSideMessage.Type.DISCONNECTED, nickname, null));
                        in.close();
                        out.close();
                        socket.close();

                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

        @Override
        public boolean hasNextMessage() {
                return !q.isEmpty();
        }

        @Override
        public ClientSideMessage getNextMessage() {
                return q.poll();
        }

        @Override
        public void sendOrder(Order order) {
                try {
                        out.writeObject((new ServerMessage(
                                        ServerSideMessage.Type.NEW_ORDER, nickname, order)));
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

}